//
//  FileDownloader.swift
//  ADKit
//
//  Created by Adoma on 2025/06/07.
//

import Foundation
import Alamofire

class FileDownloader {

    static let shared = FileDownloader()

    private var urlCallbacks: [URL: [((Result<URL, Error>) -> Void)]] = [:]
    private let callbackLock = DispatchSemaphore(value: 1)

    private init() {}

    private func synchronized<T>(_ block: () -> T) -> T {
        callbackLock.wait()
        let result = block()
        callbackLock.signal()
        return result
    }

    func download(from url: URL, destinationURL: URL, queue: DispatchQueue, completion: @escaping (Result<URL, Error>) -> Void) -> DownloadRequest? {
        
        let isFirst: Bool = synchronized {
            if urlCallbacks[url] != nil {
                urlCallbacks[url]?.append(completion)
                return false
            } else {
                urlCallbacks[url] = [completion]
                return true
            }
        }

        guard isFirst else {
            return nil
        }

        let request = AF.download(url, to: { _, _ in
            return (destinationURL, [.removePreviousFile, .createIntermediateDirectories])
        }).response(queue: queue) { response in
            self.synchronized {
                let callbacks = self.urlCallbacks[url]
                self.urlCallbacks.removeValue(forKey: url)
                
                if let afError = response.error, afError.isExplicitlyCancelledError {
                    return
                }
                
                if let destURL = response.fileURL, response.error == nil {
                    callbacks?.forEach { $0(.success(destURL)) }
                } else {
                    callbacks?.forEach { $0(.failure(response.error ?? ADError.downloadError)) }
                }
            }
        }
        
        return request
    }
}
